﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CSharpExt.Text
{
    public interface IWildcard
    {
        #region Interface
        
        bool IsMatch(String test);
         
        bool IsWildcard { get; }
        
        #endregion
    }
    
    
    public class Wildcard : IWildcard
    {
        #region Factory Methods

        public static IWildcard Create(String wildcard)
        {
            if(wildcard.IndexOf('|') > 0 || wildcard.IndexOf(',') > 0)
            {
                String[] wildcards = wildcard.Split('|', ',');
                return Create(wildcards);
            }
            else
            {
                return new Wildcard(wildcard);
            }
        }

        public static IWildcard Create(String[] wildcards)
        {
            IWildcard[] list = new Wildcard[wildcards.Length];
            for (int i = 0; i < wildcards.Length; ++i)
                list[i] = Create(wildcards[i]);
            return new WildcardList(list); 
        }

        #endregion

        #region Private Data

        private String _pattern;

        #endregion

        #region Constructor

        public Wildcard(String pattern)
        {
            _pattern = pattern;
        }

        #endregion

        #region Operations

        public bool IsMatch(String text)
        {
            return match(text, 0, 0);
        }

        public bool IsWildcard
        {
            get
            {
                return _pattern.IndexOf('*') != -1 || _pattern.IndexOf('?') != -1;
            }
        }

        #endregion

        #region Implementation

        private bool match(String text, int pat, int tat)
        {
            if(pat == _pattern.Length && tat == text.Length)
                return true;

            if(pat == _pattern.Length || tat == text.Length)
                return false;

            if (_pattern[pat] == '?')
                return match(text, pat + 1, tat + 1);

            if(_pattern[pat] == '*')
            {
                for(int tmp = tat; tmp <= text.Length; ++tmp)
                    if(match(text, pat+1, tmp))
                        return true;
                return false;
            }

            if (_pattern[pat] == text[tat])
                return match(text, pat + 1, tat + 1);

            return false;
        }

        #endregion
    }

    internal class WildcardList : IWildcard
    {
        #region Private Data

        private IWildcard[] _wildcards;

        #endregion

        #region Constructor

        internal WildcardList(IWildcard[] wildcards)
        {
            _wildcards = wildcards;
        }

        #endregion

        #region Operations


        public bool IsMatch(String text)
        {
            foreach (IWildcard wildcard in _wildcards)
            {
                if(wildcard.IsMatch(text))
                    return true;
            }
            return false;
        }

        public bool IsWildcard
        {
            get 
            {
                foreach(IWildcard wildcard in _wildcards)
                {
                    if (wildcard.IsWildcard)
                        return true;
                }
                return false;
            }
        }

        #endregion

    }
}
